#pragma once

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

#include "luster_float.hh"
#include "luster_int.hh"
#include "luster_string.hh"
#include "luster_vec.hh"

namespace luster {

#define LEXPR_TYPE_MAP(_) \
	_(S32) \
	_(F32) \
	_(BOOL) \
	_(LIST) /* (...) */ \
	_(LIST_Z) /* [..] */ \
	_(LIST_D) /* {..} */ \
	_(SYMBOL) \
	_(KEYWORD) \
	_(OP) \
	_(STRING)

typedef enum lexpr_type {
#define _(M_NAME) LEXPR_##M_NAME,
	LEXPR_TYPE_MAP(_)
#undef _
} LexprTag;

struct Lexpr {
	LexprTag tag{LexprTag::LEXPR_S32};
	union {
		S32 i32;
		F32 f32;
		Bool yes;
		Slice string;
		Vec<Lexpr> exprs;
	} as{};
};

char const *lexpr_tag_name(LexprTag tag);

void lexpr_display(Lexpr const *expr, FILE *fp);

void lexpr_deinit(Lexpr *expr);

} // namespace luster
